
//***************************************************************************
//                             
//***************************************************************************

#ifndef _VHAND_SPHERE_FILLEd_BODY_H
#define _VHAND_SPHERE_FILLEd_BODY_H

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

// system include
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>                                          

// project include
#include <defESphereSpringSystem.h>

#include "SphereTopology.h"
#include "HandConfig.h"

namespace vhand
{

//---------------------------------------------------------------------------                                                 
// Forward Declaration
//--------------------------------------------------------------------------- 

using defE::IndexRange;
using defE::IndexRanges;
using defE::Sphere;
using defE::Spring;
using defE::SphereH;
using defE::SpringH;
using defE::SphereSpringSystem;


//***************************************************************************
//                             
//***************************************************************************

/**
 */
class SphereFilledBody
{
public:
    virtual ~SphereFilledBody();
    float* openPosArrayFromCGR( struct cudaGraphicsResource *geom_cgr,
                                unsigned int possizeinbyte );
    void closePosArrayFromCGR( struct cudaGraphicsResource *geom_cgr );

    const SphereSpringSystem* getSphereSpringSystem() const { return &_sss; };
    SphereSpringSystem* editSphereSpringSystem() { return &_sss; };

    IndexRange getSphereRange() const { return IndexRange( _spheres_index, _spheres_size ); };

    void setDeltaTime( float dt ) { _dt = dt; }
    void setStepNum( unsigned int stepnum ) { _stepnum = stepnum; }
    void setSpringArg( const AdjacencyType &type, float ks, float kd, float kv = 0 );
    void setHandGeometry( Geometry *bones_geom, Geometry *skin_geom );

    const SphereTopology* getSphereTopology() const { return &_topo; }
    SphereTopology* editSphereTopology() { return &_topo; }
    const std::vector<Sphere>* getAllSphere() const { return &_allsphere; }
    std::vector<Sphere>* editAllSphere() { return &_allsphere; }
    void setShortestRadius( float sr ) { _shortestradius = sr; }
    float getShortestRadius( void ) const { return _shortestradius; }

    void initHost( void );
    void initDevice( void );
    void deformation( const IndexRanges *rs_bones,
                      const IndexRanges *rs_skin,
                      const IndexRanges *rs_spheres,
                      const Matrix4 &updatemat );
    void simulation( void );
    void updateGeometry( void );

    void initGeometry( void ) { _sss.initGeometry(); }
    void draw( void ) const { _sss.draw(); }

private:

    /** 
     */
    SphereTopology _topo;

    /** 
     */
    SphereSpringSystem _sss;
    unsigned int _stepnum;
    float _dt;
    float _kv_sphr_sphr;
    float _ks_skin_skin;
    float _ks_skin_sphr;
    float _ks_sphr_sphr;
    float _ks_sphr_bone;
    float _kd_skin_skin;
    float _kd_skin_sphr;
    float _kd_sphr_sphr;
    float _kd_sphr_bone;

    // for bones
    Geometry *_bones_geom;
    struct cudaGraphicsResource *_bones_pos_cgr;
    unsigned int _bones_pos_vbo_id;
    unsigned int _bones_pos_vbo_sizeinbyte;

    /** Indicate the start position and size of sphere from bones in the
     *  sphere-spring-system's device array.
     */
    unsigned int _bones_index;
    unsigned int _bones_size;

    // for skin
    Geometry *_skin_geom;
    struct cudaGraphicsResource *_skin_pos_cgr;
    unsigned int _skin_pos_vbo_id;
    unsigned int _skin_pos_vbo_sizeinbyte;

    /** Indicate the position and size of sphere from skin in the
     *  sphere-spring-system's device array.
     */
    unsigned int _skin_index;
    unsigned int _skin_size;


    // for spheres
    std::vector<Sphere> _allsphere;
    float _shortestradius;

    /** Indicate the position and size of sphere from spheres in the
     *  sphere-spring-system's device array.
     */
    unsigned int _spheres_index;
    unsigned int _spheres_size;

};

} // namespace vhand

#endif // _VHAND_SPHERE_FILLEd_BODY_H

